package com.yn.xgame.game;

import com.yn.xgame.ZkClient;
import com.yn.xgame.util.Utils;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * GameCenterWatcher
 * 在如logic服中使用，监听当前游戏注册在哪个center下。
 * center 注册节点： /yn/center/1 /yn/center/2 ...
 * Created by wangboo on 17/7/17.
 */
public class GameCenterWatcher implements Watcher {

    private static final Logger logger = LoggerFactory.getLogger(GameCenterWatcher.class);
    private ZkClient zkClient;
    // Map<gameName, centerTopic>
    private Map<String, String> map = new ConcurrentHashMap<>();


    public GameCenterWatcher(ZkClient zkClient) {
        this.zkClient = zkClient;
    }

    public void doWatch() {
        loadParentPath();
    }

    private void loadParentPath() {
        List<String> children = zkClient.getChildren("/center", this);
        if (children == null) {
            logger.warn("zk load center failed, /center has no children!");
            return;
        }
        children.forEach(id ->
                loadPath("/center/" + id)
        );
        logger.debug("zk GameCenterMap: {}", map);
    }

    private void loadPath(String path) {
        int id = Utils.getNo(path);
        String centerTopic = "center" + id;
        String names = zkClient.getDataAsString(path, this);
        for (String gameName : names.split(",")) {
            map.put(gameName.trim(), centerTopic);
        }
    }

    public String getCenterTopic(String gameName) {
        return map.get(gameName);
    }

    @Override
    public void process(WatchedEvent event) {
        logger.debug("zk Event: {}", event);
        if (event.getPath() == null || !event.getPath().contains("/center")) return;
        switch (event.getType()) {
            case NodeChildrenChanged:
                loadParentPath();
                break;
            case NodeCreated:
                loadParentPath();
                break;
            case NodeDeleted:
                onPathDelete(event.getPath());
                break;
        }
    }

    private void onPathDelete(String path) {
        int id = Utils.getNo(path);
        String center = "center" + id;
        List<String> removeGames = new LinkedList<>();
        map.forEach((k,v) -> {
            if (center.equals(v)) removeGames.add(k);
        });
        removeGames.forEach(k -> map.remove(k));
        logger.debug("center: {}关闭，被移除的game有：{}", removeGames);
    }
}
